package com.sam.designpatterns

import java.lang.UnsupportedOperationException

// 抽象节点
abstract class Component(protected val name: String) {
    // 具体逻辑方法由子类实现
    abstract fun doSomeThing()
    // 添加子节点
    abstract fun addChild(child: Component)
    // 移除子节点
    abstract fun removeChild(child: Component)
    // 获取对应下标的子节点
    abstract fun getChild(index: Int): Component
}

// 枝干节点
class Composite(name: String) : Component(name) {
    private val components = mutableListOf<Component>()
    override fun doSomeThing() {
        println(name)
        for (component in components) {
            component.doSomeThing()
        }
    }

    override fun addChild(child: Component) {
        components.add(child)
    }

    override fun removeChild(child: Component) {
        components.remove(child)
    }

    override fun getChild(index: Int): Component {
        return components[index]
    }
}

// 叶子节点
class Leaf(name: String) : Component(name) {
    override fun doSomeThing() {
        println(name)
    }

    override fun addChild(child: Component) {
        throw UnsupportedOperationException("叶子节点没有子节点")
    }

    override fun removeChild(child: Component) {
        throw UnsupportedOperationException("叶子节点没有子节点")
    }

    override fun getChild(index: Int): Component {
        throw UnsupportedOperationException("叶子节点没有子节点")
    }
}

fun main() {
    // 构造一个根节点
    val root = Composite("Root")

    // 构造两个枝干节点
    val branch1 = Composite("Branch1")
    val branch2 = Composite("Branch2")

    // 构造两个叶子节点
    val leaf1 = Leaf("Leaf1")
    val leaf2 = Leaf("Leaf2")

    // 将叶子节点添加至枝干节点中
    branch1.addChild(leaf1)
    branch2.addChild(leaf2)

    // 将枝干节点添加于根节点中
    root.addChild(branch1)
    root.addChild(branch2)

    // 执行方法
    root.doSomeThing()
}